/*     */ package com.zimbra.cs.mailbox;
/*     */ 
/*     */ import com.google.common.base.Objects;
/*     */ import com.google.common.base.Objects.ToStringHelper;
/*     */ import com.google.common.base.Strings;
/*     */ import com.google.common.collect.ImmutableSet;
/*     */ import com.zimbra.common.mailbox.Color;
/*     */ import com.zimbra.common.mailbox.ContactConstants;
/*     */ import com.zimbra.common.service.ServiceException;
/*     */ import com.zimbra.common.util.ByteUtil;
/*     */ import com.zimbra.common.util.Log;
/*     */ import com.zimbra.common.util.StringUtil;
/*     */ import com.zimbra.common.util.ZimbraLog;
/*     */ import com.zimbra.cs.account.Account;
/*     */ import com.zimbra.cs.account.EntryCacheDataKey;
/*     */ import com.zimbra.cs.account.Provisioning;
/*     */ import com.zimbra.cs.account.Server;
/*     */ import com.zimbra.cs.db.DbMailItem;
/*     */ import com.zimbra.cs.index.IndexDocument;
/*     */ import com.zimbra.cs.mime.ParsedContact;
/*     */ import com.zimbra.cs.store.MailboxBlob;
/*     */ import com.zimbra.cs.store.StagedBlob;
/*     */ import java.io.IOException;
/*     */ import java.io.InputStream;
/*     */ import java.io.OutputStream;
/*     */ import java.util.ArrayList;
/*     */ import java.util.Collections;
/*     */ import java.util.HashMap;
/*     */ import java.util.Iterator;
/*     */ import java.util.List;
/*     */ import java.util.Map;
/*     */ import java.util.Map.Entry;
/*     */ import java.util.Set;
/*     */ import javax.activation.DataHandler;
/*     */ import javax.activation.DataSource;
/*     */ import javax.mail.internet.MimeMessage;
/*     */ import javax.mail.util.ByteArrayDataSource;
/*     */ import org.json.JSONArray;
/*     */ import org.json.JSONException;
/*     */ import org.json.JSONObject;
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ public class Contact
/*     */   extends MailItem
/*     */ {
/*     */   private Map<String, String> fields;
/*     */   private List<Attachment> attachments;
/*     */   
/*     */   public static class Attachment
/*     */     implements DataSource
/*     */   {
/*     */     private DataHandler mDataHandler;
/*     */     private int mSize;
/*     */     private String mFieldName;
/*     */     private String mPartName;
/*     */     private static final String FN_SIZE = "size";
/*     */     private static final String FN_NAME = "name";
/*     */     private static final String FN_PART = "part";
/*     */     private static final String FN_CTYPE = "ctype";
/*     */     private static final String FN_FIELD = "field";
/*     */     
/*     */     public Attachment(byte[] content, String ctype, String field, String filename)
/*     */     {
/*  80 */       if (ctype == null) {
/*  81 */         ctype = "application/octet-stream";
/*     */       } else {
/*  83 */         ctype = ctype.toLowerCase();
/*     */       }
/*  85 */       if (content == null) {
/*  86 */         content = new byte[0];
/*     */       }
/*  88 */       ByteArrayDataSource ds = new ByteArrayDataSource(content, ctype);
/*  89 */       if (filename != null) {
/*  90 */         ds.setName(filename);
/*     */       } else {
/*  92 */         ds.setName("unknown");
/*     */       }
/*  94 */       init(new DataHandler(ds), field, content.length);
/*     */     }
/*     */     
/*     */     public Attachment(DataHandler dataHandler, String field) throws IOException
/*     */     {
/*  99 */       int size = (int)ByteUtil.getDataLength(dataHandler.getInputStream());
/* 100 */       init(dataHandler, field, size);
/*     */     }
/*     */     
/*     */     public Attachment(DataHandler dataHandler, String field, int size) {
/* 104 */       init(dataHandler, field, size);
/*     */     }
/*     */     
/*     */     private void init(DataHandler dataHandler, String field, int size) {
/* 108 */       if (dataHandler == null) {
/* 109 */         throw new NullPointerException("dataHandler cannot be null");
/*     */       }
/* 111 */       if (StringUtil.isNullOrEmpty(field)) {
/* 112 */         throw new NullPointerException("field cannot be null or empty");
/*     */       }
/* 114 */       this.mDataHandler = dataHandler;
/* 115 */       this.mFieldName = field;
/* 116 */       this.mSize = size;
/*     */     }
/*     */     
/*     */     public void setPartName(String name) {
/* 120 */       this.mPartName = name;
/*     */     }
/*     */     
/*     */     public String getContentType()
/*     */     {
/* 125 */       return this.mDataHandler.getContentType();
/*     */     }
/*     */     
/*     */     public String getName()
/*     */     {
/* 130 */       return this.mFieldName;
/*     */     }
/*     */     
/*     */     public int getSize() {
/* 134 */       return this.mSize;
/*     */     }
/*     */     
/*     */ 
/*     */ 
/*     */ 
/*     */     public InputStream getInputStream()
/*     */       throws IOException
/*     */     {
/* 143 */       if (this.mDataHandler != null) {
/* 144 */         return this.mDataHandler.getInputStream();
/*     */       }
/* 146 */       return null;
/*     */     }
/*     */     
/*     */     public OutputStream getOutputStream()
/*     */     {
/* 151 */       throw new UnsupportedOperationException();
/*     */     }
/*     */     
/*     */ 
/*     */     public byte[] getContent()
/*     */       throws IOException
/*     */     {
/* 158 */       InputStream in = null;
/* 159 */       byte[] content = null;
/*     */       try {
/* 161 */         in = getInputStream();
/* 162 */         if (in != null) {
/* 163 */           content = ByteUtil.getContent(in, this.mSize);
/*     */         }
/*     */       } finally {
/* 166 */         ByteUtil.closeStream(in);
/*     */       }
/* 168 */       return content;
/*     */     }
/*     */     
/*     */     public String getFilename() {
/* 172 */       return StringUtil.sanitizeFilename(this.mDataHandler.getName());
/*     */     }
/*     */     
/* 175 */     public String getPartName() { return this.mPartName; }
/* 176 */     public DataHandler getDataHandler() { return this.mDataHandler; }
/*     */     
/*     */ 
/*     */     Metadata asMetadata()
/*     */     {
/* 181 */       return new Metadata().put("size", this.mSize).put("name", getFilename()).put("part", this.mPartName).put("ctype", getContentType()).put("field", this.mFieldName);
/*     */     }
/*     */     
/*     */     public String toString()
/*     */     {
/* 186 */       return this.mFieldName + " [" + getContentType() + ", " + this.mSize + "B]";
/*     */     }
/*     */   }
/*     */   
/*     */   public static enum DerefGroupMembersOption
/*     */   {
/* 192 */     NONE, 
/* 193 */     INLINE_ONLY;
/*     */     
/*     */ 
/*     */ 
/*     */     private DerefGroupMembersOption() {}
/*     */   }
/*     */   
/*     */ 
/*     */ 
/* 202 */   private static final String[] EMAIL_FIELDS = { ContactConstants.A_email, ContactConstants.A_email2, ContactConstants.A_email3, ContactConstants.A_workEmail1, ContactConstants.A_workEmail2, ContactConstants.A_workEmail3 };
/*     */   
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */   private String[] emailFields;
/*     */   
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */   public static String[] getEmailFields(Account acct)
/*     */   {
/* 220 */     String[] emailFields = null;
/*     */     
/*     */ 
/* 223 */     emailFields = (String[])acct.getCachedData(EntryCacheDataKey.ACCOUNT_EMAIL_FIELDS);
/*     */     
/* 225 */     if (emailFields == null) {
/* 226 */       String[] fields = null;
/* 227 */       String emailFieldsStr = acct.getAttr("zimbraContactEmailFields");
/* 228 */       if (emailFieldsStr != null) {
/* 229 */         fields = emailFieldsStr.split(",");
/*     */       }
/* 231 */       if (fields != null)
/*     */       {
/* 233 */         List<String> temp = new ArrayList(fields.length);
/* 234 */         for (String field : fields) {
/* 235 */           if (!ContactConstants.A_dlist.equals(field))
/* 236 */             temp.add(field);
/*     */         }
/* 238 */         if (temp.size() > 0) {
/* 239 */           emailFields = (String[])temp.toArray(new String[0]);
/*     */         }
/*     */       }
/* 242 */       if (emailFields == null) {
/* 243 */         emailFields = EMAIL_FIELDS;
/*     */       }
/*     */       
/* 246 */       acct.setCachedData(EntryCacheDataKey.ACCOUNT_EMAIL_FIELDS, emailFields);
/*     */     }
/*     */     
/* 249 */     return emailFields;
/*     */   }
/*     */   
/*     */   public Contact(Mailbox mbox, MailItem.UnderlyingData data) throws ServiceException {
/* 253 */     this(mbox, data, false);
/*     */   }
/*     */   
/*     */   public Contact(Mailbox mbox, MailItem.UnderlyingData data, boolean skipCache) throws ServiceException {
/* 257 */     super(mbox, data, skipCache);
/* 258 */     if (this.mData.type != MailItem.Type.CONTACT.toByte()) {
/* 259 */       throw new IllegalArgumentException();
/*     */     }
/* 261 */     this.emailFields = getEmailFields(getAccount());
/*     */   }
/*     */   
/*     */   public String getSender()
/*     */   {
/*     */     try {
/* 267 */       return getFileAsString();
/*     */     } catch (ServiceException e) {}
/* 269 */     return "";
/*     */   }
/*     */   
/*     */ 
/*     */   public String getSortSender()
/*     */   {
/* 275 */     String sender = getSender();
/*     */     
/* 277 */     return DbMailItem.normalize(sender, 128);
/*     */   }
/*     */   
/*     */   public String get(String fieldName)
/*     */   {
/* 282 */     return (String)this.fields.get(fieldName);
/*     */   }
/*     */   
/*     */   public Map<String, String> getAllFields()
/*     */   {
/* 287 */     return new HashMap(this.fields);
/*     */   }
/*     */   
/*     */   public Map<String, String> getFields()
/*     */   {
/* 292 */     HashMap<String, String> result = new HashMap(this.fields);
/*     */     try {
/* 294 */       String hiddenAttrList = Provisioning.getInstance().getLocalServer().getContactHiddenAttributes();
/* 295 */       if (hiddenAttrList != null) {
/* 296 */         for (String attr : hiddenAttrList.split(",")) {
/* 297 */           result.remove(attr);
/*     */         }
/*     */       }
/*     */     } catch (ServiceException e) {
/* 301 */       ZimbraLog.mailop.warn("can't get A_zimbraContactHiddenAttributes", e);
/*     */     }
/* 303 */     return result;
/*     */   }
/*     */   
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */   public List<Attachment> getAttachments()
/*     */   {
/* 312 */     if (this.attachments == null) {
/* 313 */       return Collections.emptyList();
/*     */     }
/* 315 */     return new ArrayList(this.attachments);
/*     */   }
/*     */   
/*     */ 
/*     */ 
/*     */ 
/*     */   public MimeMessage getMimeMessage(boolean runConverters)
/*     */     throws ServiceException
/*     */   {
/* 324 */     return MessageCache.getMimeMessage(this, runConverters);
/*     */   }
/*     */   
/*     */ 
/*     */ 
/*     */ 
/*     */   public String getSortName()
/*     */     throws ServiceException
/*     */   {
/* 333 */     return getFileAsString(this.fields, true);
/*     */   }
/*     */   
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */   public String getFileAsString()
/*     */     throws ServiceException
/*     */   {
/* 356 */     return getFileAsString(this.fields, false);
/*     */   }
/*     */   
/*     */   public static String getFileAsString(Map<String, String> fields) throws ServiceException {
/* 360 */     return getFileAsString(fields, false);
/*     */   }
/*     */   
/*     */   private static String getFileAsString(Map<String, String> fields, boolean phonetic)
/*     */     throws ServiceException
/*     */   {
/* 366 */     String fileAs = (String)fields.get(ContactConstants.A_fileAs);
/* 367 */     String[] fileParts = fileAs == null ? null : fileAs.split(":", 2);
/* 368 */     int fileAsInt = 1;
/* 369 */     if (fileParts != null) {
/*     */       try {
/* 371 */         fileAsInt = Integer.parseInt(fileParts[0]);
/* 372 */         if ((fileAsInt < 0) || (fileAsInt > 8))
/* 373 */           throw ServiceException.INVALID_REQUEST("invalid fileAs value: " + fileAs, null);
/*     */       } catch (NumberFormatException e) {
/* 375 */         throw ServiceException.INVALID_REQUEST("invalid fileAs value: " + fileAs, null);
/*     */       }
/*     */     }
/*     */     
/* 379 */     String company = null;
/* 380 */     if (phonetic) {
/* 381 */       company = (String)fields.get(ContactConstants.A_phoneticCompany);
/*     */     }
/* 383 */     if (Strings.isNullOrEmpty(company)) {
/* 384 */       company = (String)fields.get(ContactConstants.A_company);
/*     */     }
/* 386 */     company = Strings.nullToEmpty(company);
/*     */     
/* 388 */     String first = null;
/* 389 */     if (phonetic) {
/* 390 */       first = (String)fields.get(ContactConstants.A_phoneticFirstName);
/*     */     }
/* 392 */     if (Strings.isNullOrEmpty(first)) {
/* 393 */       first = (String)fields.get(ContactConstants.A_firstName);
/*     */     }
/* 395 */     first = Strings.nullToEmpty(first);
/*     */     
/* 397 */     String last = null;
/* 398 */     if (phonetic) {
/* 399 */       last = (String)fields.get(ContactConstants.A_phoneticLastName);
/*     */     }
/* 401 */     if (Strings.isNullOrEmpty(last)) {
/* 402 */       last = (String)fields.get(ContactConstants.A_lastName);
/*     */     }
/* 404 */     last = Strings.nullToEmpty(last);
/*     */     
/* 406 */     StringBuilder result = new StringBuilder();
/* 407 */     switch (fileAsInt) {
/*     */     case 8: 
/* 409 */       if ((fileParts.length == 2) && (!fileParts[1].trim().equals(""))) {
/* 410 */         result.append(fileParts[1].trim());
/*     */       }
/*     */       else
/* 413 */         throw ServiceException.INVALID_REQUEST("invalid fileAs value: " + fileAs, null);
/*     */       break;
/*     */     case 1: default: 
/* 416 */       result.append(last);
/* 417 */       if ((first.length() > 0) && (last.length() > 0))
/* 418 */         result.append(", ");
/* 419 */       result.append(first);
/* 420 */       break;
/*     */     case 2: 
/* 422 */       result.append(first);
/* 423 */       if ((first.length() > 0) && (last.length() > 0))
/* 424 */         result.append(' ');
/* 425 */       result.append(last);
/* 426 */       break;
/*     */     case 3: 
/* 428 */       result.append(company);
/* 429 */       break;
/*     */     case 4: 
/* 431 */       result.append(last);
/* 432 */       if ((first.length() > 0) && (last.length() > 0))
/* 433 */         result.append(", ");
/* 434 */       result.append(first);
/* 435 */       if (company.length() > 0)
/* 436 */         result.append(" (").append(company).append(')');
/*     */       break;
/*     */     case 5: 
/* 439 */       result.append(first);
/* 440 */       if ((first.length() > 0) && (last.length() > 0))
/* 441 */         result.append(' ');
/* 442 */       result.append(last);
/* 443 */       if (company.length() > 0)
/* 444 */         result.append(" (").append(company).append(')');
/*     */       break;
/*     */     case 6: 
/* 447 */       result.append(company);
/* 448 */       if ((first.length() > 0) || (last.length() > 0)) {
/* 449 */         result.append(" (").append(last);
/* 450 */         if ((first.length() > 0) && (last.length() > 0))
/* 451 */           result.append(", ");
/* 452 */         result.append(first).append(')');
/*     */       }
/*     */       break;
/*     */     case 7: 
/* 456 */       result.append(company);
/* 457 */       if ((first.length() > 0) || (last.length() > 0)) {
/* 458 */         result.append(" (").append(first);
/* 459 */         if ((first.length() > 0) && (last.length() > 0))
/* 460 */           result.append(' ');
/* 461 */         result.append(last).append(')');
/*     */       }
/*     */       break;
/*     */     }
/* 465 */     return result.toString().trim();
/*     */   }
/*     */   
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */   public static void normalizeFileAs(Map<String, String> attrs)
/*     */   {
/* 474 */     String fileAs = (String)attrs.get(ContactConstants.A_fullName);
/* 475 */     if ((fileAs == null) || (fileAs.trim().length() == 0)) {
/* 476 */       return;
/*     */     }
/* 478 */     String last = (String)attrs.get(ContactConstants.A_lastName);
/* 479 */     last = last == null ? "" : last;
/* 480 */     String first = (String)attrs.get(ContactConstants.A_firstName);
/* 481 */     first = first == null ? "" : first;
/* 482 */     String company = (String)attrs.get(ContactConstants.A_company);
/* 483 */     company = company == null ? "" : company;
/* 484 */     String middle = (String)attrs.get(ContactConstants.A_middleName);
/* 485 */     middle = middle == null ? "" : middle;
/*     */     
/*     */ 
/* 488 */     if (!middle.isEmpty()) {
/* 489 */       String lastFirstMiddle = last + ", " + first + " " + middle;
/* 490 */       String firstMiddleLast = first + " " + middle + " " + last;
/* 491 */       if ((fileAs.equals(lastFirstMiddle)) || (fileAs.equals(firstMiddleLast))) {
/* 492 */         fileAs = last + ", " + first;
/*     */       }
/*     */     }
/*     */     
/*     */ 
/* 497 */     StringBuilder sb = new StringBuilder();
/* 498 */     sb.append(last);
/* 499 */     if ((last.length() > 0) && (first.length() > 0)) sb.append(", ");
/* 500 */     sb.append(first);
/* 501 */     if (sb.toString().equals(fileAs)) {
/* 502 */       attrs.put(ContactConstants.A_fileAs, Integer.valueOf(1).toString());
/* 503 */       return;
/*     */     }
/*     */     
/*     */ 
/* 507 */     sb = new StringBuilder();
/* 508 */     sb.append(first);
/* 509 */     if ((last.length() > 0) && (first.length() > 0)) sb.append(' ');
/* 510 */     sb.append(last);
/* 511 */     if (sb.toString().equals(fileAs)) {
/* 512 */       attrs.put(ContactConstants.A_fileAs, Integer.valueOf(2).toString());
/* 513 */       return;
/*     */     }
/*     */     
/*     */ 
/* 517 */     if (company.equals(fileAs)) {
/* 518 */       attrs.put(ContactConstants.A_fileAs, Integer.valueOf(3).toString());
/* 519 */       return;
/*     */     }
/*     */     
/*     */ 
/* 523 */     sb = new StringBuilder();
/* 524 */     sb.append(last);
/* 525 */     if ((last.length() > 0) && (first.length() > 0)) sb.append(", ");
/* 526 */     sb.append(first);
/* 527 */     if (company.length() > 0) sb.append(" (").append(company).append(')');
/* 528 */     if (sb.toString().equals(fileAs)) {
/* 529 */       attrs.put(ContactConstants.A_fileAs, Integer.valueOf(4).toString());
/* 530 */       return;
/*     */     }
/*     */     
/*     */ 
/* 534 */     sb = new StringBuilder();
/* 535 */     sb.append(first);
/* 536 */     if ((last.length() > 0) && (first.length() > 0)) sb.append(' ');
/* 537 */     sb.append(last);
/* 538 */     if (company.length() > 0) sb.append(" (").append(company).append(')');
/* 539 */     if (sb.toString().equals(fileAs)) {
/* 540 */       attrs.put(ContactConstants.A_fileAs, Integer.valueOf(5).toString());
/* 541 */       return;
/*     */     }
/*     */     
/*     */ 
/* 545 */     sb = new StringBuilder();
/* 546 */     sb.append(company);
/* 547 */     if ((last.length() > 0) || (first.length() > 0)) {
/* 548 */       sb.append(" (").append(last);
/* 549 */       if ((last.length() > 0) && (first.length() > 0)) sb.append(", ");
/* 550 */       sb.append(first).append(')');
/*     */     }
/* 552 */     if (sb.toString().equals(fileAs)) {
/* 553 */       attrs.put(ContactConstants.A_fileAs, Integer.valueOf(6).toString());
/* 554 */       return;
/*     */     }
/*     */     
/*     */ 
/* 558 */     sb = new StringBuilder();
/* 559 */     sb.append(company);
/* 560 */     if ((last.length() > 0) || (first.length() > 0)) {
/* 561 */       sb.append(" (").append(first);
/* 562 */       if ((last.length() > 0) && (first.length() > 0)) sb.append(' ');
/* 563 */       sb.append(last).append(')');
/*     */     }
/* 565 */     if (sb.toString().equals(fileAs)) {
/* 566 */       attrs.put(ContactConstants.A_fileAs, Integer.valueOf(7).toString());
/* 567 */       return;
/*     */     }
/*     */     
/*     */ 
/* 571 */     attrs.put(ContactConstants.A_fileAs, Integer.valueOf(8).toString() + ':' + fileAs);
/*     */   }
/*     */   
/*     */ 
/*     */ 
/*     */   public List<String> getEmailAddresses()
/*     */   {
/* 578 */     return getEmailAddresses(this.emailFields, this.fields, DerefGroupMembersOption.INLINE_ONLY);
/*     */   }
/*     */   
/*     */   public List<String> getEmailAddresses(DerefGroupMembersOption derefGroupMemberOpt) {
/* 582 */     return getEmailAddresses(this.emailFields, this.fields, derefGroupMemberOpt);
/*     */   }
/*     */   
/*     */   public static final boolean isEmailField(String[] emailFields, String fieldName) {
/* 586 */     if (fieldName == null)
/* 587 */       return false;
/* 588 */     String lcField = fieldName.toLowerCase();
/* 589 */     for (String e : emailFields) {
/* 590 */       if (lcField.equals(e))
/* 591 */         return true;
/*     */     }
/* 593 */     if (lcField.equals(ContactConstants.A_dlist))
/* 594 */       return true;
/* 595 */     return false;
/*     */   }
/*     */   
/*     */   public static final List<String> getEmailAddresses(String[] fieldNames, Map<String, String> fields, DerefGroupMembersOption derefGroupMemberOpt)
/*     */   {
/* 600 */     List<String> result = new ArrayList();
/* 601 */     for (String name : fieldNames) {
/* 602 */       String addr = (String)fields.get(name);
/* 603 */       if ((addr != null) && (!addr.trim().isEmpty())) {
/* 604 */         result.add(addr);
/*     */       }
/*     */     }
/*     */     
/* 608 */     if (derefGroupMemberOpt != DerefGroupMembersOption.NONE) {
/* 609 */       String encodedGroupMembers = (String)fields.get(ContactConstants.A_groupMember);
/* 610 */       if (encodedGroupMembers != null) {
/*     */         try {
/* 612 */           ContactGroup contactGroup = ContactGroup.init(encodedGroupMembers);
/* 613 */           List<String> emailAddrs = contactGroup.getInlineEmailAddresses();
/* 614 */           for (String addr : emailAddrs) {
/* 615 */             result.add(addr);
/*     */           }
/*     */         } catch (ServiceException e) {
/* 618 */           ZimbraLog.contact.warn("unable to decode contact group", e);
/*     */         }
/*     */       }
/*     */     }
/*     */     
/* 623 */     return result;
/*     */   }
/*     */   
/*     */   boolean isTaggable()
/*     */   {
/* 628 */     return true;
/*     */   }
/*     */   
/*     */   boolean isCopyable()
/*     */   {
/* 633 */     return true;
/*     */   }
/*     */   
/*     */   boolean isMovable()
/*     */   {
/* 638 */     return true;
/*     */   }
/*     */   
/*     */   boolean isMutable()
/*     */   {
/* 643 */     return true;
/*     */   }
/*     */   
/*     */   boolean canHaveChildren()
/*     */   {
/* 648 */     return false;
/*     */   }
/*     */   
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */   static Contact create(int id, Folder folder, MailboxBlob mblob, ParsedContact pc, int flags, Tag.NormalizedTags ntags, MailItem.CustomMetadata custom)
/*     */     throws ServiceException
/*     */   {
/* 675 */     if ((folder == null) || (!folder.canContain(MailItem.Type.CONTACT))) {
/* 676 */       throw MailServiceException.CANNOT_CONTAIN();
/*     */     }
/* 678 */     if (!folder.canAccess((short)4)) {
/* 679 */       throw ServiceException.PERM_DENIED("you do not have the required rights on the folder");
/*     */     }
/* 681 */     Mailbox mbox = folder.getMailbox();
/* 682 */     mbox.updateContactCount(1);
/*     */     
/* 684 */     MailItem.UnderlyingData data = new MailItem.UnderlyingData();
/* 685 */     data.id = id;
/* 686 */     data.type = MailItem.Type.CONTACT.toByte();
/* 687 */     data.folderId = folder.getId();
/* 688 */     if ((!folder.inSpam()) || (mbox.getAccount().getBooleanAttr("zimbraJunkMessagesIndexingEnabled", false))) {
/* 689 */       data.indexId = MailItem.IndexStatus.DEFERRED.id();
/*     */     }
/* 691 */     data.imapId = id;
/* 692 */     data.locator = (mblob == null ? null : mblob.getLocator());
/* 693 */     data.setBlobDigest(pc.getDigest());
/* 694 */     data.size = pc.getSize();
/* 695 */     data.date = mbox.getOperationTimestamp();
/* 696 */     data.setFlags(flags | (pc.hasAttachment() ? Flag.BITMASK_ATTACHED : 0));
/* 697 */     data.setTags(ntags);
/* 698 */     data.metadata = encodeMetadata(DEFAULT_COLOR_RGB, 1, 1, custom, pc.getFields(), pc.getAttachments());
/* 699 */     data.contentChanged(mbox);
/*     */     
/* 701 */     if (ZimbraLog.mailop.isInfoEnabled()) {
/* 702 */       String email = "null";
/* 703 */       if (pc.getFields() != null) {
/* 704 */         email = (String)pc.getFields().get(ContactConstants.A_email);
/*     */       }
/* 706 */       ZimbraLog.mailop.info("adding contact %s: id=%d, folderId=%d, folderName=%s.", new Object[] { email, Integer.valueOf(data.id), Integer.valueOf(folder.getId()), folder.getName() });
/*     */     }
/*     */     
/*     */ 
/* 710 */     new DbMailItem(mbox).setSender(getFileAsString(pc.getFields())).create(data);
/*     */     
/* 712 */     Contact contact = new Contact(mbox, data);
/* 713 */     contact.finishCreation(null);
/* 714 */     if (contact.fields.isEmpty()) {
/* 715 */       throw ServiceException.INVALID_REQUEST("contact must have fields", null);
/*     */     }
/* 717 */     return contact;
/*     */   }
/*     */   
/*     */   MailboxBlob setContent(StagedBlob staged, Object content) throws ServiceException, IOException
/*     */   {
/* 722 */     ZimbraLog.mailop.info("modifying contact %s: id=%d, folderId=%d, folderName=%s.", new Object[] { get(ContactConstants.A_email), Integer.valueOf(getId()), Integer.valueOf(getFolderId()), getFolder().getName() });
/*     */     
/* 724 */     return super.setContent(staged, content);
/*     */   }
/*     */   
/*     */   public List<IndexDocument> generateIndexData() throws MailItem.TemporaryIndexingException
/*     */   {
/* 729 */     this.mMailbox.lock.lock();
/*     */     try {
/* 731 */       ParsedContact pc = new ParsedContact(this);
/* 732 */       pc.analyze(this.mMailbox);
/* 733 */       if (pc.hasTemporaryAnalysisFailure()) {
/* 734 */         throw new MailItem.TemporaryIndexingException();
/*     */       }
/* 736 */       return pc.getLuceneDocuments(this.mMailbox);
/*     */     } catch (ServiceException e) { List localList;
/* 738 */       ZimbraLog.index.error("Failed to index contact id=%d", new Object[] { Integer.valueOf(getId()) });
/* 739 */       return Collections.emptyList();
/*     */     } finally {
/* 741 */       this.mMailbox.lock.release();
/*     */     }
/*     */   }
/*     */   
/*     */   void reanalyze(Object data, long newSize) throws ServiceException
/*     */   {
/* 747 */     if (!(data instanceof ParsedContact)) {
/* 748 */       throw ServiceException.FAILURE("cannot reanalyze non-ParsedContact object", null);
/*     */     }
/* 750 */     ParsedContact pc = (ParsedContact)data;
/*     */     
/* 752 */     markItemModified(65572);
/* 753 */     this.fields = pc.getFields();
/* 754 */     if ((this.fields == null) || (this.fields.isEmpty())) {
/* 755 */       throw ServiceException.INVALID_REQUEST("contact must have fields", null);
/*     */     }
/* 757 */     this.attachments = pc.getAttachments();
/* 758 */     if ((this.attachments != null) && (this.attachments.size() > 0)) {
/* 759 */       for (Attachment attach : this.attachments)
/*     */       {
/*     */ 
/* 762 */         attach.mDataHandler = new DataHandler(new AttachmentDataSource(this, attach.mPartName));
/*     */       }
/*     */     }
/* 765 */     this.mData.unsetFlag(Flag.FlagInfo.ATTACHED);
/* 766 */     if (pc.hasAttachment()) {
/* 767 */       this.mData.setFlag(Flag.FlagInfo.ATTACHED);
/*     */     }
/* 769 */     saveData(new DbMailItem(this.mMailbox).setSender(getFileAsString(this.fields)));
/*     */   }
/*     */   
/*     */ 
/*     */   MailItem copy(Folder folder, int id, String uuid, MailItem parent)
/*     */     throws IOException, ServiceException
/*     */   {
/* 776 */     this.mMailbox.updateContactCount(1);
/* 777 */     return super.copy(folder, id, uuid, parent);
/*     */   }
/*     */   
/*     */ 
/*     */   MailItem icopy(Folder folder, int copyId, String copyUuid)
/*     */     throws IOException, ServiceException
/*     */   {
/* 784 */     this.mMailbox.updateContactCount(1);
/* 785 */     return super.icopy(folder, copyId, copyUuid);
/*     */   }
/*     */   
/*     */   MailItem.PendingDelete getDeletionInfo()
/*     */     throws ServiceException
/*     */   {
/* 791 */     MailItem.PendingDelete info = super.getDeletionInfo();
/* 792 */     info.contacts = 1;
/* 793 */     return info;
/*     */   }
/*     */   
/*     */   void decodeMetadata(Metadata meta) throws ServiceException
/*     */   {
/*     */     Metadata metaAttrs;
/* 799 */     if (meta.containsKey("fld"))
/*     */     {
/* 801 */       super.decodeMetadata(meta);
/* 802 */       Metadata metaAttrs = meta.getMap("fld");
/*     */       
/* 804 */       MetadataList mlAttach = meta.getList("att", true);
/* 805 */       if (mlAttach != null) {
/* 806 */         this.attachments = new ArrayList(mlAttach.size());
/* 807 */         for (int i = 0; i < mlAttach.size(); i++) {
/* 808 */           Metadata attachMeta = mlAttach.getMap(i);
/* 809 */           String fieldName = attachMeta.get("field");
/* 810 */           String partName = attachMeta.get("part");
/* 811 */           int size = (int)attachMeta.getLong("size");
/* 812 */           DataHandler dh = new DataHandler(new AttachmentDataSource(this, partName));
/* 813 */           Attachment attachment = new Attachment(dh, fieldName, size);
/* 814 */           attachment.setPartName(partName);
/* 815 */           this.attachments.add(attachment);
/*     */         }
/*     */       }
/*     */     }
/*     */     else
/*     */     {
/* 821 */       metaAttrs = meta;
/*     */     }
/*     */     
/* 824 */     this.fields = new HashMap();
/* 825 */     for (Map.Entry<String, ?> entry : metaAttrs.asMap().entrySet()) {
/* 826 */       this.fields.put(entry.getKey(), entry.getValue().toString());
/*     */     }
/*     */   }
/*     */   
/*     */   Metadata encodeMetadata(Metadata meta)
/*     */   {
/* 832 */     return encodeMetadata(meta, this.mRGBColor, this.mMetaVersion, this.mVersion, this.mExtendedData, this.fields, this.attachments);
/*     */   }
/*     */   
/*     */   private static String encodeMetadata(Color color, int metaVersion, int version, MailItem.CustomMetadata custom, Map<String, String> fields, List<Attachment> attachments) {
/* 836 */     MailItem.CustomMetadata.CustomMetadataList extended = custom == null ? null : custom.asList();
/* 837 */     return encodeMetadata(new Metadata(), color, metaVersion, version, extended, fields, attachments).toString();
/*     */   }
/*     */   
/*     */   static Metadata encodeMetadata(Metadata meta, Color color, int metaVersion, int version, MailItem.CustomMetadata.CustomMetadataList extended, Map<String, String> fields, List<Attachment> attachments)
/*     */   {
/* 842 */     meta.put("fld", new Metadata(fields));
/* 843 */     if ((attachments != null) && (!attachments.isEmpty())) {
/* 844 */       MetadataList mlist = new MetadataList();
/* 845 */       for (Attachment attach : attachments)
/* 846 */         mlist.add(attach.asMetadata());
/* 847 */       meta.put("att", mlist);
/*     */     }
/* 849 */     return MailItem.encodeMetadata(meta, color, null, metaVersion, version, extended);
/*     */   }
/*     */   
/*     */   public String toString()
/*     */   {
/* 854 */     Objects.ToStringHelper helper = Objects.toStringHelper(this);
/* 855 */     appendCommonMembers(helper);
/* 856 */     for (Map.Entry<String, String> entry : this.fields.entrySet()) {
/* 857 */       helper.add((String)entry.getKey(), entry.getValue());
/*     */     }
/* 859 */     return helper.toString();
/*     */   }
/*     */   
/*     */   public String getVCardUID() {
/* 863 */     return (String)this.fields.get("vcardUID");
/*     */   }
/*     */   
/*     */   public String getXProp(String xprop) {
/* 867 */     return (String)getXProps().get(xprop);
/*     */   }
/*     */   
/*     */   public Map<String, String> getXProps() {
/* 871 */     return decodeXProps((String)this.fields.get("vcardXProps"));
/*     */   }
/*     */   
/*     */   public void setXProps(Map<String, String> xprops) {
/* 875 */     this.fields.put("vcardXProps", encodeXProps(xprops));
/*     */   }
/*     */   
/*     */ 
/*     */ 
/*     */   public boolean isGroup()
/*     */   {
/* 882 */     return "group".equals(get(ContactConstants.A_type));
/*     */   }
/*     */   
/*     */   public static boolean isGroup(Map<String, ? extends Object> attrs) {
/* 886 */     return "group".equals(attrs.get(ContactConstants.A_type));
/*     */   }
/*     */   
/*     */   public boolean isContactGroup() {
/* 890 */     return (isGroup()) && (get(ContactConstants.A_groupMember) != null);
/*     */   }
/*     */   
/* 893 */   private static Set<String> SMIME_FIELDS = ImmutableSet.of(ContactConstants.A_userCertificate, ContactConstants.A_userSMIMECertificate);
/*     */   private static final String ZMVAL = "ZMVAL";
/*     */   private static final String ZMVALENCODED = "{\"ZMVAL\":";
/*     */   
/* 897 */   public static Set<String> getSMIMECertFields() { return SMIME_FIELDS; }
/*     */   
/*     */   public static boolean isSMIMECertField(String fieldName)
/*     */   {
/* 901 */     return SMIME_FIELDS.contains(fieldName);
/*     */   }
/*     */   
/*     */   public static Map<String, String> decodeXProps(String xpropStr) {
/* 905 */     HashMap<String, String> xprops = new HashMap();
/* 906 */     if ((xpropStr == null) || (xpropStr.length() == 0))
/* 907 */       return xprops;
/*     */     try {
/* 909 */       JSONObject xpropObj = new JSONObject(xpropStr);
/* 910 */       Iterator<?> iter = xpropObj.keys();
/* 911 */       while (iter.hasNext()) {
/* 912 */         String key = (String)iter.next();
/* 913 */         xprops.put(key, xpropObj.get(key).toString());
/*     */       }
/*     */     } catch (JSONException e) {
/* 916 */       ZimbraLog.mailop.debug("can't get xprop %s", xpropStr, e);
/*     */     }
/* 918 */     return xprops;
/*     */   }
/*     */   
/*     */ 
/*     */ 
/*     */   public static String encodeXProps(Map<String, String> xprops)
/*     */   {
/* 925 */     JSONObject jsonobj = new JSONObject();
/*     */     try {
/* 927 */       for (String s : xprops.keySet())
/* 928 */         jsonobj.put(s, xprops.get(s));
/*     */     } catch (JSONException e) {
/* 930 */       ZimbraLog.mailop.debug("can't encode xprops to JSONObject", e);
/*     */     }
/* 932 */     return jsonobj.toString();
/*     */   }
/*     */   
/*     */ 
/*     */   public static String encodeMultiValueAttr(String[] attrs)
/*     */     throws JSONException
/*     */   {
/* 939 */     JSONObject jsonobj = new JSONObject();
/* 940 */     for (String s : attrs)
/* 941 */       jsonobj.append("ZMVAL", s);
/* 942 */     return jsonobj.toString();
/*     */   }
/*     */   
/* 945 */   public static boolean isMultiValueAttr(String attr) { return attr.startsWith("{\"ZMVAL\":"); }
/*     */   
/*     */   public static String[] parseMultiValueAttr(String attr) throws JSONException {
/* 948 */     if (!isMultiValueAttr(attr))
/* 949 */       return new String[] { attr };
/* 950 */     JSONObject jsonobj = new JSONObject(attr);
/* 951 */     JSONArray array = jsonobj.getJSONArray("ZMVAL");
/* 952 */     String[] mv = new String[array.length()];
/* 953 */     for (int i = 0; i < mv.length; i++)
/* 954 */       mv[i] = array.getString(i);
/* 955 */     return mv;
/*     */   }
/*     */   
/* 958 */   public static JSONArray getMultiValueAttrArray(String attr) throws JSONException { if (!isMultiValueAttr(attr)) {
/* 959 */       JSONObject jsonobj = new JSONObject();
/* 960 */       jsonobj.append("ZMVAL", attr);
/* 961 */       return jsonobj.getJSONArray("ZMVAL");
/*     */     }
/* 963 */     JSONObject jsonobj = new JSONObject(attr);
/* 964 */     JSONArray array = jsonobj.getJSONArray("ZMVAL");
/* 965 */     return array;
/*     */   }
/*     */ }


/* Location:              /home/mint/zimbrastore.jar!/com/zimbra/cs/mailbox/Contact.class
 * Java compiler version: 7 (51.0)
 * JD-Core Version:       0.7.1
 */